package com.xbx.zuul.filter;

import com.google.gson.Gson;
import com.xbx.baseweb.controller.RequesUtils;
import com.xbx.baseweb.controller.ResultUtils;
import com.xbx.baseweb.model.ResponseModel;
import com.xbx.zuul.utils.UserUtlis;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 权限过滤器
 *
 * @author 89005691
 * @create 2018-09-11 18:28
 */
@Slf4j
public class AnyOfRolesAuthorizationFilter extends RolesAuthorizationFilter {

    private String notpermissionHost;

    @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;

        // 如果是option请求，直接放行
        if ("OPTIONS".equalsIgnoreCase(httpServletRequest.getMethod())) {

            log.info("OPTIONS请求通行，请求路径{}", httpServletRequest.getRequestURI());
            return true;
        }

        final Subject subject = getSubject(request, response);
        final String[] rolesArray = (String[]) mappedValue;

        if (rolesArray == null || rolesArray.length == 0) {

            return true;
        }

        // 有一个角色满足即通过
        for (String roleName : rolesArray) {

            if (subject.hasRole(roleName)) {

                return true;
            }
        }

        return false;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {

        boolean isAjax = false;

        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse servletResponse = (HttpServletResponse) response;

        if (RequesUtils.requestIsAjax(servletRequest)) {

            isAjax = true;
            servletResponse.setContentType("application/json;charset=UTF-8");
            // 允许跨域的主机地址
            servletResponse.setHeader("Access-Control-Allow-Origin", notpermissionHost);
            // 允许跨域的请求方法GET, POST, HEAD 等
            servletResponse.setHeader("Access-Control-Allow-Methods", "*");
            // 重新预检验跨域的缓存时间 (s)
            servletResponse.setHeader("Access-Control-Max-Age", "3600");
            // 允许跨域的请求头
            servletResponse.setHeader("Access-Control-Allow-Headers", "*");
            // 是否携带cookie
            servletResponse.setHeader("Access-Control-Allow-Credentials", "true");
        }

        if (UserUtlis.getLoginUserInfo() == null) {

            log.info("获取用户信息{}", new Gson().toJson(UserUtlis.getLoginUserInfo()));

            if (isAjax) {

                // 未登录
                ResponseModel responseModel = ResultUtils.fail(-1, "未登录");
                outputJson(servletResponse, responseModel);
            } else {

                saveRequestAndRedirectToLogin(request, response);
            }
        } else {
            if (RequesUtils.requestIsAjax(servletRequest)) {

                // 没权限
                ResponseModel responseModel = ResultUtils.fail(HttpStatus.SC_UNAUTHORIZED, "没有权限");
                outputJson(servletResponse, responseModel);
            } else {

                if (StringUtils.hasText(getUnauthorizedUrl())) {

                    WebUtils.issueRedirect(request, response, getUnauthorizedUrl());
                }
            }
        }

        return false;
    }

    public void outputJson(ServletResponse response, ResponseModel responseModel){

        PrintWriter printWriter = null;

        try {

            printWriter = response.getWriter();
            printWriter.print(new Gson().toJson(responseModel));
            printWriter.flush();
        }catch (Exception e){

            log.error("输出json信息出错", e);
        }finally {

            if(printWriter != null){

                printWriter.close();
            }
        }

    }

    public String getNotpermissionHost() {
        return notpermissionHost;
    }

    public void setNotpermissionHost(String notpermissionHost) {
        this.notpermissionHost = notpermissionHost;
    }
}
